86 lines
2.3 KiB
Rust
Raw Normal View History

use crate::generator::util::output_rendered_template;
use crate::generator::util::templates::{filters, TemplateCommon};
use crate::generator::{archive::ArchivePost, HtmlContent, Post};
use askama::Template;
use chrono::Datelike;
use compute_graph::{
builder::GraphBuilder,
rule::{Input, InputVisitable, Rule},
synchronicity::Asynchronous,
};
use std::collections::HashMap;
pub fn make_graph(
builder: &mut GraphBuilder<super::GraphOutput, Asynchronous>,
posts: &[Input<Post<HtmlContent>>],
) -> Input<()> {
let posts_by_year = builder.add_rule(PostsByYear(posts.into()));
let archive = builder.add_rule(GenerateArchive(posts_by_year));
// TODO: paginated year posts indexes
archive
}
struct PostsByYear(Vec<Input<Post<HtmlContent>>>);
impl InputVisitable for PostsByYear {
fn visit_inputs(&self, visitor: &mut impl compute_graph::rule::InputVisitor) {
for input in &self.0 {
visitor.visit(input);
}
}
}
impl Rule for PostsByYear {
type Output = HashMap<i32, Vec<ArchivePost>>;
fn evaluate(&mut self) -> Self::Output {
let mut map = HashMap::new();
for input in &self.0 {
let post = input.value();
let year_posts: &mut Vec<ArchivePost> =
map.entry(post.metadata.date.year()).or_default();
year_posts.push(ArchivePost {
permalink: post.permalink(),
title: post.metadata.title.clone(),
});
}
map
}
}
#[derive(InputVisitable)]
struct GenerateArchive(Input<<PostsByYear as Rule>::Output>);
impl Rule for GenerateArchive {
type Output = ();
fn evaluate(&mut self) -> Self::Output {
let posts_by_year = self.input_0();
let mut years = posts_by_year
.iter()
.map(|(y, ps)| (*y, ps))
.collect::<Vec<_>>();
years.sort_by_key(|(year, _)| *year);
years.reverse();
let template = ArchiveTemplate { years: &years };
output_rendered_template(&template, "archive/index.html").expect("generate archive");
}
}
#[derive(Template)]
#[template(path = "archive.html")]
struct ArchiveTemplate<'a> {
years: &'a [(i32, &'a Vec<ArchivePost>)],
}
impl<'a> ArchiveTemplate<'a> {
fn permalink(&self) -> &'static str {
"/archive/"
}
}
impl<'a> TemplateCommon for ArchiveTemplate<'a> {}