88 lines
2.6 KiB
Rust
Raw Normal View History

use std::path::PathBuf;
use crate::error::CustomError;
2023-10-29 13:51:32 -04:00
use super::footnote_definition::IRealFootnoteDefinition;
2023-10-29 22:31:29 -04:00
use super::IDocumentElement;
use super::IHeading;
use super::ISection;
use super::RefRegistry;
#[derive(Debug)]
pub(crate) struct BlogPostPage {
/// Relative path from the root of the blog post.
pub(crate) path: PathBuf,
pub(crate) title: Option<String>,
pub(crate) children: Vec<IDocumentElement>,
2023-10-29 13:51:32 -04:00
pub(crate) footnotes: Vec<IRealFootnoteDefinition>,
}
impl BlogPostPage {
// TODO: Move path into the registry so I can give this a standard interface like the others.
pub(crate) async fn new<'a, 'b, 'parse, P: Into<PathBuf>>(
path: P,
registry: RefRegistry<'b, 'parse>,
2023-10-29 14:14:10 -04:00
document: &'b organic::types::Document<'parse>,
) -> Result<BlogPostPage, CustomError> {
let path = path.into();
let mut children = Vec::new();
if let Some(section) = document.zeroth_section.as_ref() {
children.push(IDocumentElement::Section(
ISection::new(registry.clone(), section).await?,
));
}
for heading in document.children.iter() {
children.push(IDocumentElement::Heading(
IHeading::new(registry.clone(), heading).await?,
));
}
2023-10-29 15:36:15 -04:00
let footnotes = {
let footnote_definitions: Vec<_> = {
let registry = registry.lock().unwrap();
let ret = registry
.get_footnote_ids()
.map(|(id, def)| (id, def.clone()))
.collect();
ret
};
2023-10-29 15:36:15 -04:00
let mut ret = Vec::new();
for (id, def) in footnote_definitions.into_iter() {
ret.push(IRealFootnoteDefinition::new(registry.clone(), id, def).await?);
2023-10-29 15:36:15 -04:00
}
ret
};
2023-10-29 13:51:32 -04:00
Ok(BlogPostPage {
path,
2023-10-23 18:39:54 -04:00
title: get_title(&document),
children,
2023-10-29 15:36:15 -04:00
footnotes,
})
}
/// Get the output path relative to the post directory.
pub(crate) fn get_output_path(&self) -> PathBuf {
let mut ret = self.path.clone();
ret.set_extension("html");
ret
}
}
2023-10-23 18:39:54 -04:00
fn get_title(document: &organic::types::Document<'_>) -> Option<String> {
organic::types::AstNode::from(document)
.iter_all_ast_nodes()
.filter_map(|node| match node {
organic::types::AstNode::Keyword(kw) if kw.key.eq_ignore_ascii_case("title") => {
Some(kw)
}
_ => None,
})
.last()
.map(|kw| kw.value.to_owned())
}