natter/src/intermediate/page.rs
Tom Alexander f9377d7609
Make converstion to intermediate state async.
We are going to need to do things like call external tools for syntax highlighting so we are going to need async in there eventually.
2023-10-27 15:55:19 -04:00

66 lines
1.8 KiB
Rust

use std::path::PathBuf;
use crate::error::CustomError;
use super::registry::Registry;
use super::IDocumentElement;
use super::IHeading;
use super::ISection;
#[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>,
}
impl BlogPostPage {
pub(crate) async fn new<'parse, P: Into<PathBuf>>(
path: P,
registry: &mut Registry<'parse>,
document: &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, section).await?,
));
}
for heading in document.children.iter() {
children.push(IDocumentElement::Heading(
IHeading::new(registry, heading).await?,
));
}
Ok(BlogPostPage {
path,
title: get_title(&document),
children,
})
}
/// 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
}
}
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())
}