use serde::Serialize;
use uuid::Uuid;
use crate::store::hierarchy::Hierarchy;
use crate::store::node::NodeKind;
use super::markdown_html::slugify;
pub struct Chapter {
pub title: String,
pub file: String,
pub content: Vec<ContentNode>,
pub sections: Vec<NavSection>,
}
pub struct ContentNode {
pub id: Uuid,
pub kind: NodeKind,
pub anchor: Option<String>,
pub title: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct NavItem {
pub title: String,
pub href: String,
pub current: bool,
pub sections: Vec<NavSection>,
}
#[derive(Debug, Clone, Serialize)]
pub struct NavSection {
pub title: String,
pub href: String,
}
pub struct SiteModel {
pub chapters: Vec<Chapter>,
pub front_matter: Vec<Uuid>,
}
pub fn build(h: &Hierarchy, book_id: Uuid, timeline_ids: &std::collections::HashSet<Uuid>) -> SiteModel {
let mut chapters = Vec::new();
let mut front_matter = Vec::new();
for (i, child) in h.children_of(Some(book_id)).into_iter().enumerate() {
match child.kind {
NodeKind::Paragraph => front_matter.push(child.id),
NodeKind::Chapter => {
if timeline_ids.contains(&child.id) {
continue;
}
let file = format!("ch{:02}-{}.html", i + 1, slugify(&child.title));
let mut content = Vec::new();
let mut sections = Vec::new();
for id in h.collect_subtree(child.id) {
if id == child.id {
continue;
}
let Some(node) = h.get(id) else { continue };
match node.kind {
NodeKind::Subchapter => {
let anchor = slugify(&node.title);
sections.push(NavSection {
title: node.title.clone(),
href: format!("{file}#{anchor}"),
});
content.push(ContentNode {
id,
kind: NodeKind::Subchapter,
anchor: Some(anchor),
title: node.title.clone(),
});
}
NodeKind::Paragraph => {
if node.event.is_some() {
continue; }
content.push(ContentNode {
id,
kind: NodeKind::Paragraph,
anchor: None,
title: node.title.clone(),
});
}
_ => {}
}
}
chapters.push(Chapter { title: child.title.clone(), file, content, sections });
}
_ => {}
}
}
SiteModel { chapters, front_matter }
}
pub fn nav(chapters: &[Chapter], current_file: &str) -> Vec<NavItem> {
chapters
.iter()
.map(|c| NavItem {
title: c.title.clone(),
href: c.file.clone(),
current: c.file == current_file,
sections: c.sections.clone(),
})
.collect()
}