use crate::{
config::Config,
theme::{LocaleInfo, NavItem, PageContext, SidebarGroup, Theme, ThemeFactory},
};
use std::sync::Arc;
pub struct HtmlGenerator {
theme: Arc<dyn Theme>,
}
impl Clone for HtmlGenerator {
fn clone(&self) -> Self {
Self { theme: Arc::clone(&self.theme) }
}
}
impl HtmlGenerator {
pub fn new() -> Self {
let config = Config::default();
Self::with_config_and_theme(config, "default")
}
pub fn with_config_and_theme(config: Config, theme_name: &str) -> Self {
let theme = ThemeFactory::create(theme_name, config.clone()).unwrap_or_else(|_| ThemeFactory::create("default", config).expect("Failed to create default theme"));
Self { theme }
}
pub fn with_config(config: Config) -> Self {
Self::with_config_and_theme(config, "default")
}
pub fn switch_theme(&mut self, theme_name: &str) -> Result<(), Box<dyn std::error::Error>> {
let config = self.theme.config().clone();
self.theme = ThemeFactory::create(theme_name, config)?;
Ok(())
}
pub fn current_theme_name(&self) -> &str {
self.theme.name()
}
pub fn available_themes() -> Vec<&'static str> {
ThemeFactory::available_themes()
}
pub fn generate(&self, content: &str, title: &str) -> String {
let site_title = self.theme.config().title.clone().unwrap_or_default();
let site_title_str = site_title.to_string();
let page_title = if !title.is_empty() && title != site_title_str { format!("{} | {}", title, site_title_str) } else { site_title_str.clone() };
let nav_items: Vec<NavItem> = Vec::new();
let sidebar_group = SidebarGroup { text: "文档".to_string(), items: Vec::new() };
let sidebar_groups = vec![sidebar_group];
let (has_footer, has_footer_message, footer_message, has_footer_copyright, footer_copyright) = if let Some(footer) = &self.theme.config().theme.footer { (true, footer.message.is_some(), footer.message.clone().unwrap_or_default(), footer.copyright.is_some(), footer.copyright.clone().unwrap_or_default()) } else { (false, false, String::new(), false, String::new()) };
let locale_infos: Vec<LocaleInfo> = Vec::new();
let context = PageContext { page_title, site_title: site_title_str, content: content.to_string(), nav_items, sidebar_groups, current_path: "".to_string(), has_footer, has_footer_message, footer_message, has_footer_copyright, footer_copyright, current_lang: "zh-CN".to_string(), available_locales: locale_infos, root_path: "./".to_string() };
self.theme.render_page(&context).unwrap_or_else(|_| format!("<html><head><title>{}</title></head><body><h1>{}</h1>{}</body></html>", title, title, content))
}
pub fn generate_with_context(&self, context: &PageContext) -> Result<String, Box<dyn std::error::Error>> {
self.theme.render_page(context)
}
pub fn static_resources(&self) -> Vec<(String, String)> {
self.theme.static_resources()
}
}
impl Default for HtmlGenerator {
fn default() -> Self {
Self::new()
}
}