use std::fs;
use std::path::Path;
use anyhow::{Context, Result};
use minijinja::Environment;
use walkdir::WalkDir;
use super::templates::describe_template_error;
use super::utils::normalize_path;
pub(super) fn render_pages(
root: &Path,
html_root: &Path,
env: &Environment<'static>,
verbose: bool,
) -> Result<usize> {
let pages_dir = root.join("pages");
if !pages_dir.exists() {
return Ok(0);
}
let mut files = Vec::new();
for entry in WalkDir::new(&pages_dir) {
let entry = entry?;
if entry.file_type().is_file() {
files.push(entry.into_path());
}
}
files.sort();
let mut rendered_pages = 0usize;
for path in files {
let relative = path.strip_prefix(&pages_dir).with_context(|| {
format!(
"path {} is not under {}",
path.display(),
pages_dir.display()
)
})?;
let output_path = html_root.join(relative);
if let Some(parent) = output_path.parent() {
fs::create_dir_all(parent)
.with_context(|| format!("failed to create directory {}", parent.display()))?;
}
if !is_html_file(&path) {
fs::copy(&path, &output_path).with_context(|| {
format!(
"failed to copy page asset from {} to {}",
path.display(),
output_path.display()
)
})?;
super::utils::log_status(
verbose,
"PAGE",
format!("Copied {}", normalize_path(relative)),
);
continue;
}
let source = fs::read_to_string(&path)
.with_context(|| format!("failed to read page template {}", path.display()))?;
let scope = format!("rendering standalone page {}", normalize_path(relative));
let template_name = normalize_path(relative);
let rendered = env
.render_str(&source, minijinja::context! {})
.map_err(|err| describe_template_error(&scope, &template_name, err))?;
fs::write(&output_path, rendered)
.with_context(|| format!("failed to write page {}", output_path.display()))?;
super::utils::log_status(
verbose,
"PAGE",
format!("Rendered {}", normalize_path(relative)),
);
rendered_pages += 1;
}
Ok(rendered_pages)
}
fn is_html_file(path: &Path) -> bool {
path.extension()
.and_then(|ext| ext.to_str())
.is_some_and(|ext| ext.eq_ignore_ascii_case("html"))
}