2023-10-23 16:03:37 -04:00
|
|
|
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
|
|
|
|
2023-12-19 17:09:11 -05:00
|
|
|
use super::macros::intermediate;
|
2023-10-27 13:05:34 -04:00
|
|
|
use super::IDocumentElement;
|
|
|
|
use super::IHeading;
|
|
|
|
use super::ISection;
|
2023-12-19 17:09:11 -05:00
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub(crate) struct BlogPostPageInput<'b, 'parse> {
|
|
|
|
path: PathBuf,
|
|
|
|
document: &'b organic::types::Document<'parse>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'b, 'parse> BlogPostPageInput<'b, 'parse> {
|
|
|
|
pub(crate) fn new<P: Into<PathBuf>>(
|
|
|
|
path: P,
|
|
|
|
document: &'b organic::types::Document<'parse>,
|
|
|
|
) -> BlogPostPageInput<'b, 'parse> {
|
|
|
|
BlogPostPageInput {
|
|
|
|
path: path.into(),
|
|
|
|
document,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-24 00:36:08 -04:00
|
|
|
|
2023-10-23 16:03:37 -04:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub(crate) struct BlogPostPage {
|
|
|
|
/// Relative path from the root of the blog post.
|
2023-10-23 20:30:43 -04:00
|
|
|
pub(crate) path: PathBuf,
|
2023-10-23 16:03:37 -04:00
|
|
|
|
2023-10-23 20:30:43 -04:00
|
|
|
pub(crate) title: Option<String>,
|
2023-10-24 00:36:08 -04:00
|
|
|
|
2023-12-17 16:57:37 -05:00
|
|
|
pub(crate) date: Option<String>,
|
|
|
|
|
2023-10-27 13:05:34 -04:00
|
|
|
pub(crate) children: Vec<IDocumentElement>,
|
2023-10-29 13:51:32 -04:00
|
|
|
|
|
|
|
pub(crate) footnotes: Vec<IRealFootnoteDefinition>,
|
2023-10-23 16:03:37 -04:00
|
|
|
}
|
|
|
|
|
2023-12-19 17:09:11 -05:00
|
|
|
intermediate!(
|
|
|
|
BlogPostPage,
|
|
|
|
BlogPostPageInput<'orig, 'parse>,
|
|
|
|
original,
|
|
|
|
registry,
|
|
|
|
{
|
2023-10-24 00:36:08 -04:00
|
|
|
let mut children = Vec::new();
|
2023-12-19 17:09:11 -05:00
|
|
|
if let Some(section) = original.document.zeroth_section.as_ref() {
|
2023-10-27 15:55:19 -04:00
|
|
|
children.push(IDocumentElement::Section(
|
2023-10-29 21:19:30 -04:00
|
|
|
ISection::new(registry.clone(), section).await?,
|
2023-10-27 15:55:19 -04:00
|
|
|
));
|
2023-10-24 00:36:08 -04:00
|
|
|
}
|
2023-12-19 17:09:11 -05:00
|
|
|
for heading in original.document.children.iter() {
|
2023-10-27 15:55:19 -04:00
|
|
|
children.push(IDocumentElement::Heading(
|
2023-10-29 21:19:30 -04:00
|
|
|
IHeading::new(registry.clone(), heading).await?,
|
2023-10-27 15:55:19 -04:00
|
|
|
));
|
2023-10-24 00:36:08 -04:00
|
|
|
}
|
|
|
|
|
2023-10-29 15:36:15 -04:00
|
|
|
let footnotes = {
|
2023-10-29 21:19:30 -04:00
|
|
|
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() {
|
2023-10-29 21:19:30 -04:00
|
|
|
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
|
|
|
|
2023-10-23 16:03:37 -04:00
|
|
|
Ok(BlogPostPage {
|
2023-12-19 17:09:11 -05:00
|
|
|
path: original.path,
|
|
|
|
title: get_title(original.document),
|
|
|
|
date: get_date(original.document),
|
2023-10-24 00:36:08 -04:00
|
|
|
children,
|
2023-10-29 15:36:15 -04:00
|
|
|
footnotes,
|
2023-10-23 16:03:37 -04:00
|
|
|
})
|
|
|
|
}
|
2023-12-19 17:09:11 -05:00
|
|
|
);
|
2023-10-23 20:30:43 -04:00
|
|
|
|
2023-12-19 17:09:11 -05:00
|
|
|
impl BlogPostPage {
|
2023-10-23 20:30:43 -04:00
|
|
|
/// 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 16:03:37 -04:00
|
|
|
}
|
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())
|
|
|
|
}
|
2023-12-17 16:57:37 -05:00
|
|
|
|
|
|
|
fn get_date(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("date") => Some(kw),
|
|
|
|
_ => None,
|
|
|
|
})
|
|
|
|
.last()
|
|
|
|
.map(|kw| kw.value.to_owned())
|
|
|
|
}
|