use std::collections::HashMap;
use hauchiwa::{Blueprint, Output, task};
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>("examples/assets/content/*.md")?;
let taxonomy = task!(config, |_, posts| {
let mut tags = HashMap::new();
for post in posts.values() {
for tag in &post.metadata.tags {
tags.entry(tag.clone())
.or_insert_with(Vec::new)
.push(post.metadata.title.clone());
}
}
Ok(Taxonomy { tags })
});
task!(config, |_, posts, taxonomy| {
let mut pages = Vec::new();
for post in posts.values() {
let tag_counts = post
.metadata
.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.metadata.title, tag_counts
);
let stem = post.path.file_stem().unwrap_or("unknown");
pages.push(Output {
url: format!("{}/index.html", stem).into(),
content,
});
}
Ok(pages)
});
task!(config, |_ctx, posts, taxonomy| {
let mut xml =
String::from(r#"<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">"#);
for post in posts.values() {
let stem = post.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 {
url: "sitemap.xml".into(),
content: xml,
})
});
config.finish().build(())?;
Ok(())
}