crepuscularity-cli 0.7.29

crepus CLI — scaffolding and builds for Crepuscularity (UNSTABLE; in active development).
use std::io;
use std::path::{Path, PathBuf};
use std::process::Command;

use serde_json::json;

use crate::crepus_toml::DocsHookConfig;

#[derive(Clone, Debug)]
pub(crate) struct DocsHookTheme {
    pub(crate) accent: String,
    pub(crate) accent_soft: String,
    pub(crate) surface: String,
    pub(crate) text: String,
    pub(crate) muted: String,
    pub(crate) border: String,
}

pub(crate) fn docs_src_path(site_dir: &Path, hook: &DocsHookConfig) -> PathBuf {
    let src = hook.src.as_deref().unwrap_or("../docs");
    absolutize(site_dir, src)
}

pub(crate) fn run_docs_hook(
    site_dir: &Path,
    out_docs_dir: &Path,
    hook: &DocsHookConfig,
    site_name: &str,
    theme: &DocsHookTheme,
) -> io::Result<()> {
    let docs_src = docs_src_path(site_dir, hook);
    if !docs_src.is_dir() {
        return Ok(());
    }

    let theme_json = json!({
        "accent": theme.accent,
        "accent_soft": theme.accent_soft,
        "surface": theme.surface,
        "text": theme.text,
        "muted": theme.muted,
        "border": theme.border,
    })
    .to_string();

    let docs_src_arg = docs_src.to_string_lossy().into_owned();
    let out_docs_arg = out_docs_dir.to_string_lossy().into_owned();

    let status = Command::new(&hook.command)
        .current_dir(site_dir)
        .args(&hook.args)
        .args([
            "--docs-src",
            &docs_src_arg,
            "--out-dir",
            &out_docs_arg,
            "--site-name",
            site_name,
            "--theme-json",
            &theme_json,
        ])
        .status()?;

    if status.success() {
        Ok(())
    } else {
        Err(io::Error::other(format!("docs hook exited with {status}")))
    }
}

fn absolutize(base: &Path, raw: &str) -> PathBuf {
    let path = Path::new(raw);
    if path.is_absolute() {
        path.to_path_buf()
    } else {
        let joined = base.join(path);
        std::fs::canonicalize(&joined).unwrap_or(joined)
    }
}