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(())
|
||
|
}
|