75 lines
2.2 KiB
Rust
75 lines
2.2 KiB
Rust
use super::posts::{HtmlContent, Post};
|
|
use super::util::output_rendered_template;
|
|
use askama::Template;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
pub trait PaginatableTemplate<'a>: Template {
|
|
fn with_posts(
|
|
&'a self,
|
|
posts: &'a [&'a Post<HtmlContent>],
|
|
pagination_info: PaginationInfo,
|
|
) -> Self;
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct PaginationInfo {
|
|
pub page: usize,
|
|
pub total_pages: usize,
|
|
// Relative to path of the file being generated
|
|
pub next_href: Option<String>,
|
|
// Relative to path of the file being generated
|
|
pub prev_href: Option<String>,
|
|
}
|
|
|
|
const SIZE: usize = 5;
|
|
|
|
pub fn render_paginated<'a, T: PaginatableTemplate<'a>>(
|
|
template: &'a T,
|
|
posts: &'a [&'a Post<HtmlContent>],
|
|
base_path: impl AsRef<Path>,
|
|
) -> Result<(), std::io::Error> {
|
|
// div_ceil is unstable, so we do it ourselves
|
|
let total_pages = (posts.len() as f32 / SIZE as f32).ceil() as usize;
|
|
let mut buf: PathBuf = base_path.as_ref().into();
|
|
for (chunk_idx, chunk) in posts.chunks(SIZE).enumerate() {
|
|
let page = chunk_idx + 1;
|
|
let next_page = if page < total_pages {
|
|
Some(page + 1)
|
|
} else {
|
|
None
|
|
};
|
|
let prev_page = if page > 1 { Some(page - 1) } else { None };
|
|
|
|
if page == 1 {
|
|
buf.push("index.html");
|
|
let chunk_template = template.with_posts(
|
|
chunk,
|
|
PaginationInfo {
|
|
page,
|
|
total_pages,
|
|
next_href: next_page.map(|p| format!("./{}/", p)),
|
|
prev_href: None,
|
|
},
|
|
);
|
|
output_rendered_template(&chunk_template, &buf)?;
|
|
buf.pop();
|
|
}
|
|
|
|
let chunk_template = template.with_posts(
|
|
chunk,
|
|
PaginationInfo {
|
|
page,
|
|
total_pages,
|
|
next_href: next_page.map(|p| format!("../{}/", p)),
|
|
prev_href: prev_page.map(|p| format!("../{}/", p)),
|
|
},
|
|
);
|
|
buf.push(page.to_string());
|
|
buf.push("index.html");
|
|
output_rendered_template(&chunk_template, &buf)?;
|
|
buf.pop();
|
|
buf.pop();
|
|
}
|
|
Ok(())
|
|
}
|