2023-12-17 15:23:40 -05:00
|
|
|
use serde::Serialize;
|
|
|
|
|
2023-12-19 15:42:37 -05:00
|
|
|
use super::macros::render;
|
|
|
|
use super::render_context::RenderContext;
|
2023-12-17 15:23:40 -05:00
|
|
|
use crate::context::RenderDocumentElement;
|
|
|
|
use crate::context::RenderRealFootnoteDefinition;
|
|
|
|
use crate::error::CustomError;
|
2023-12-19 10:47:03 -05:00
|
|
|
use crate::intermediate::get_web_path;
|
2023-12-17 15:23:40 -05:00
|
|
|
use crate::intermediate::BlogPost;
|
|
|
|
|
|
|
|
use super::GlobalSettings;
|
|
|
|
use super::PageHeader;
|
|
|
|
|
2023-12-19 15:42:37 -05:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub(crate) struct RenderBlogStreamInput<'a, 'b> {
|
|
|
|
original: &'a [&'b BlogPost],
|
|
|
|
older_link: Option<String>,
|
|
|
|
newer_link: Option<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> RenderBlogStreamInput<'a, 'b> {
|
|
|
|
pub(crate) fn new(
|
|
|
|
original: &'a [&'b BlogPost],
|
|
|
|
older_link: Option<String>,
|
|
|
|
newer_link: Option<String>,
|
|
|
|
) -> RenderBlogStreamInput<'a, 'b> {
|
|
|
|
RenderBlogStreamInput {
|
|
|
|
original,
|
|
|
|
older_link,
|
|
|
|
newer_link,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-17 15:23:40 -05:00
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
#[serde(tag = "type")]
|
|
|
|
#[serde(rename = "blog_stream")]
|
|
|
|
pub(crate) struct RenderBlogStream {
|
|
|
|
global_settings: GlobalSettings,
|
|
|
|
page_header: Option<PageHeader>,
|
|
|
|
children: Vec<RenderBlogStreamEntry>,
|
2023-12-19 14:13:29 -05:00
|
|
|
stream_pagination: Option<RenderBlogStreamPagination>,
|
2023-12-17 15:23:40 -05:00
|
|
|
}
|
|
|
|
|
2023-12-19 15:42:37 -05:00
|
|
|
render!(
|
|
|
|
RenderBlogStream,
|
|
|
|
RenderBlogStreamInput,
|
|
|
|
original,
|
|
|
|
render_context,
|
|
|
|
{
|
2023-12-19 10:47:03 -05:00
|
|
|
let css_files = vec![
|
|
|
|
// get_web_path(
|
|
|
|
// config,
|
|
|
|
// output_directory,
|
|
|
|
// output_file,
|
|
|
|
// "stylesheet/reset.css",
|
|
|
|
// )?,
|
2023-12-19 15:42:37 -05:00
|
|
|
get_web_path(
|
|
|
|
render_context.config,
|
|
|
|
render_context.output_directory,
|
|
|
|
render_context.output_file,
|
|
|
|
"stylesheet/main.css",
|
|
|
|
)?,
|
2023-12-19 10:47:03 -05:00
|
|
|
];
|
|
|
|
let js_files = vec![get_web_path(
|
2023-12-19 15:42:37 -05:00
|
|
|
render_context.config,
|
|
|
|
render_context.output_directory,
|
|
|
|
render_context.output_file,
|
2023-12-19 10:47:03 -05:00
|
|
|
"blog_post.js",
|
|
|
|
)?];
|
|
|
|
let global_settings = GlobalSettings::new(
|
2023-12-19 15:42:37 -05:00
|
|
|
render_context.config.get_site_title().map(str::to_string),
|
2023-12-19 10:47:03 -05:00
|
|
|
css_files,
|
|
|
|
js_files,
|
|
|
|
);
|
|
|
|
let page_header = PageHeader::new(
|
2023-12-19 15:42:37 -05:00
|
|
|
render_context.config.get_site_title().map(str::to_string),
|
|
|
|
Some(get_web_path(
|
|
|
|
render_context.config,
|
|
|
|
render_context.output_directory,
|
|
|
|
render_context.output_file,
|
|
|
|
"",
|
|
|
|
)?),
|
2023-12-19 10:47:03 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
let children = original
|
2023-12-19 15:42:37 -05:00
|
|
|
.original
|
2023-12-19 10:47:03 -05:00
|
|
|
.into_iter()
|
2023-12-19 15:42:37 -05:00
|
|
|
.map(|blog_post| RenderBlogStreamEntry::new(render_context.clone(), blog_post))
|
2023-12-19 10:47:03 -05:00
|
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
|
|
|
2023-12-19 15:42:37 -05:00
|
|
|
let stream_pagination = if original.older_link.is_some() || original.newer_link.is_some() {
|
|
|
|
Some(RenderBlogStreamPagination::new(
|
|
|
|
original.older_link.clone(),
|
|
|
|
original.newer_link.clone(),
|
|
|
|
)?)
|
2023-12-19 14:13:29 -05:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2023-12-19 10:47:03 -05:00
|
|
|
Ok(RenderBlogStream {
|
|
|
|
global_settings,
|
|
|
|
page_header: Some(page_header),
|
|
|
|
children,
|
2023-12-19 14:13:29 -05:00
|
|
|
stream_pagination,
|
2023-12-19 10:47:03 -05:00
|
|
|
})
|
2023-12-17 15:23:40 -05:00
|
|
|
}
|
2023-12-19 15:42:37 -05:00
|
|
|
);
|
2023-12-17 15:23:40 -05:00
|
|
|
|
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
pub(crate) struct RenderBlogStreamEntry {
|
|
|
|
/// The title that will be shown visibly on the page.
|
|
|
|
title: Option<String>,
|
|
|
|
|
|
|
|
self_link: Option<String>,
|
|
|
|
|
|
|
|
children: Vec<RenderDocumentElement>,
|
|
|
|
|
|
|
|
footnotes: Vec<RenderRealFootnoteDefinition>,
|
|
|
|
}
|
2023-12-19 10:47:03 -05:00
|
|
|
|
2023-12-19 15:42:37 -05:00
|
|
|
render!(RenderBlogStreamEntry, BlogPost, original, render_context, {
|
|
|
|
// TODO: This link is probably wrong.
|
|
|
|
let link_to_blog_post = get_web_path(
|
|
|
|
render_context.config,
|
|
|
|
render_context.output_directory,
|
|
|
|
render_context.output_file,
|
|
|
|
render_context
|
|
|
|
.output_file
|
|
|
|
.strip_prefix(render_context.output_directory)?,
|
|
|
|
)?;
|
|
|
|
|
|
|
|
// TODO: Should I guess an index page instead of erroring out?
|
|
|
|
let index_page = original
|
|
|
|
.get_index_page()
|
|
|
|
.ok_or_else(|| format!("Blog post {} needs an index page.", original.id))?;
|
|
|
|
|
|
|
|
let title = index_page.title.clone();
|
|
|
|
|
|
|
|
// TODO: Handle footnotes.
|
|
|
|
let children = index_page
|
|
|
|
.children
|
|
|
|
.iter()
|
|
|
|
.map(|child| RenderDocumentElement::new(render_context.clone(), child))
|
|
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
|
|
|
|
|
|
Ok(RenderBlogStreamEntry {
|
|
|
|
title,
|
|
|
|
self_link: Some(link_to_blog_post),
|
|
|
|
children,
|
|
|
|
footnotes: Vec::new(),
|
|
|
|
})
|
|
|
|
});
|
2023-12-19 14:13:29 -05:00
|
|
|
|
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
pub(crate) struct RenderBlogStreamPagination {
|
|
|
|
older_link: Option<String>,
|
|
|
|
newer_link: Option<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RenderBlogStreamPagination {
|
|
|
|
fn new(
|
|
|
|
older_link: Option<String>,
|
|
|
|
newer_link: Option<String>,
|
|
|
|
) -> Result<RenderBlogStreamPagination, CustomError> {
|
|
|
|
Ok(RenderBlogStreamPagination {
|
|
|
|
older_link,
|
|
|
|
newer_link,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|