use std::collections::HashMap;
use hauchiwa::{Blueprint, Output, output::OutputData};
use serde::Deserialize;
#[derive(Clone, Deserialize)]
struct Post {
title: String,
#[serde(default)]
tags: Vec<String>,
}
#[derive(Clone)]
struct Taxonomy {
tags: HashMap<String, Vec<String>>,
}
fn main() -> anyhow::Result<()> {
let mut config = Blueprint::<()>::new();
let posts = config
.load_documents::<Post>()
.source("examples/assets/content/*.md")
.register()?;
let taxonomy = config.task().depends_on(posts).run(|_, posts| {
let mut tags = HashMap::new();
for post in posts {
for tag in &post.matter.tags {
tags.entry(tag.clone())
.or_insert_with(Vec::new)
.push(post.matter.title.clone());
}
}
Ok(Taxonomy { tags })
});
config
.task()
.depends_on((posts, taxonomy))
.run(|_, (posts, taxonomy)| {
let mut pages = Vec::new();
for post in posts {
let tag_counts = post
.matter
.tags
.iter()
.map(|t| {
let count = taxonomy.tags.get(t).map(|v| v.len()).unwrap_or(0);
format!("{} ({})", t, count)
})
.collect::<Vec<_>>()
.join(", ");
let content = format!("<h1>{}</h1><p>Tags: {}</p>", post.matter.title, tag_counts);
let stem = post.meta.path.file_stem().unwrap_or("unknown");
pages.push(Output {
path: format!("{}/index.html", stem).into(),
data: OutputData::Utf8(content),
});
}
Ok(pages)
});
config
.task()
.depends_on((posts, taxonomy))
.run(|_, (posts, taxonomy)| {
let mut xml =
String::from(r#"<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">"#);
for post in posts {
let stem = post.meta.path.file_stem().unwrap_or("unknown");
xml.push_str(&format!("<url><loc>/{}</loc></url>", stem));
}
for tag in taxonomy.tags.keys() {
xml.push_str(&format!("<url><loc>/tags/{}</loc></url>", tag));
}
xml.push_str("</urlset>");
Ok(Output {
path: "sitemap.xml".into(),
data: OutputData::Binary(xml.into()),
})
});
config.finish().build(())?;
Ok(())
}