use crate::core::backend::GeneratedFile;
use crate::core::config::{Language, ResolvedCrateConfig};
use crate::core::ir::ApiSurface;
use std::path::PathBuf;
mod fallback;
mod paths;
mod template;
mod template_env;
#[cfg(test)]
mod tests;
pub fn generate_readmes(
api: &ApiSurface,
config: &ResolvedCrateConfig,
languages: &[Language],
) -> anyhow::Result<Vec<GeneratedFile>> {
let mut files = vec![];
for &lang in languages {
if let Some(file) = generate_readme(api, config, lang)? {
files.push(file);
}
}
Ok(files)
}
fn generate_readme(
api: &ApiSurface,
config: &ResolvedCrateConfig,
lang: Language,
) -> anyhow::Result<Option<GeneratedFile>> {
if matches!(lang, Language::Rust) && !rust_readme_explicitly_configured(config) {
return Ok(None);
}
if matches!(lang, Language::C | Language::Jni) {
return Ok(None);
}
if let Some(readme_cfg) = &config.readme {
if let Some(template_dir) = &readme_cfg.template_dir {
let workspace_root = config.workspace_root.clone().unwrap_or_else(|| PathBuf::from("."));
let abs_template_dir = workspace_root.join(template_dir);
if abs_template_dir.exists() {
if let Some(file) =
template::try_template_readme(api, config, lang, readme_cfg, &workspace_root, &abs_template_dir)?
{
return Ok(Some(file));
}
}
}
}
Ok(Some(fallback::generate_readme_hardcoded(api, config, lang)?))
}
fn rust_readme_explicitly_configured(config: &ResolvedCrateConfig) -> bool {
let Some(readme_cfg) = &config.readme else {
return false;
};
let Some(rust_cfg) = readme_cfg.languages.get("rust") else {
return false;
};
rust_cfg
.get("output_path")
.or_else(|| rust_cfg.get("output"))
.and_then(|v| v.as_str())
.is_some()
}